#!/usr/bin/env python
"""
Checks for a list of status codes and a list of 
websites to see if they are running or giving problems.

A list of sites should be in the same directory as this script.
The sites should have a full http address like:
http://example.com

The name of the file should be "config.ini"

This script would then take line by line, all the addresses 
in the file and check them.
"""

import sys
# Without this, webstatus won't be able to find other
# resources to import
sys.path.append('/etc/webstatus')

import smtplib
import urllib2
import dbwork
import os
from mailer import mailer
from subprocess import Popen
import optparse, subprocess, sys, time
from signal import SIGTERM

# List of error codes we are interested in.
# Note how 401 is not here
errorcodes =  [400, 402, 403, 404, 405, 406, 407, 408, 409, 410, 
				411, 412, 413, 414, 415, 416, 417, 500, 501, 502, 503, 
				504, 505, 506, 507, 508, 509]

# Will parse the config.ini and append the sites here
websites = []

# All the errors will be appended to this list
errors_list = []

problem_sites = []

def start():
	"""
	Double forks the process in the background
	to avoid zombies and writes the pid
	in /var/run/name.pid
	"""
	daemon = "/var/run/webstatus.pid"
	print "Starting the webstatus daemon."
	sys.stdout.flush()
	sys.stderr.flush()
	try:
		pid = os.fork()
		if pid > 0:
			sys.exit(0)
	except OSError, exc:
		sys.exit("%s: fork #1 failed: (%d) %s\n" % (sys.argv[0],
		exc.errno, exc.strerror))

	os.chdir("/")
	os.umask(0)
	os.setsid()

	try:
		pid = os.fork()
		if pid > 0:
			sys.exit(0)
	except OSError, exc:
		sys.exit("%s: fork #2 failed: (%d) %s\n" % (sys.argv[0],
		exc.errno, exc.strerror))
	pid_file =  open(daemon, "w")
	pid = str(os.getpid())
	print pid
	pid_file.write(pid+"\n")
	pid_file.close
#Lets try to write to a log file:
	stdin = "/var/log/webstatus/log"
	stdout = "/var/log/webstatus/log"
	stderr = "/var/log/webstatus/log"
	si = open(stdin, 'r')
	so = open(stdout, 'a+')
	se = open(stderr, 'a+', 0)
	os.dup2(si.fileno(), sys.stdin.fileno())
	os.dup2(so.fileno(), sys.stdout.fileno())
	os.dup2(se.fileno(), sys.stderr.fileno())



def stop():
	"""
	Stops the running process with the
	corresponding pid.
	"""

	daemon = "/var/run/webstatus.pid"
	print "Stopping the webstatus daemon"
	pidfile = open(daemon, "r")
	pid = pidfile.readline()
	print "With pid number %s" % pid
	os.kill(int(pid), SIGTERM)
	remove = "rm -f /var/run/webstatus.pid"
	subprocess.call(remove, shell=True)

def spawn(website):
	"""calls suburlcheck.py with a domain"""
	command = "/etc/webstatus/subwebstatus %s" % website
	Popen(command, shell=True)

def check_error_domains():
	"""Checks websites[] with database to avoid re-sending alerts"""
	for line in dbwork.query():
		for site in websites:
			if line[0] == site:
				websites.remove(line[0])

def get_sites():
	""" Parses the config.ini file looking for sites"""
	file = open("/etc/webstatus/config.ini")
	for line in file:
		websites.append(line.strip('\n'))

def errors(website):
	"""Iterates the error list against the websites 
	and checks for any problems"""
	try:
		urllib2.urlopen(website)
	except urllib2.HTTPError, e:
		for err in errorcodes:
			if e.code == err:
				error = "\n Url %s gave code %s" % (website, err)
				errors_list.append(error)
				dbwork.insert(website)
				spawn(website)
	except urllib2.URLError, e:
		error = "\n Something went wrong with %s Reason: %s" % (website, e.reason[1])
		errors_list.append(error) 
		dbwork.insert(website)
		spawn(website)

def notify(errors_list, subj):
	""" Sends the email with the information
	gathered about errors """
	user = ""
	passwd = ""
	to = [""]
	subject = subj
	text = errors_list
	mailer(user, passwd, to, subject, text)

def purge():
	del errors_list[:]
	del problem_sites[:]
	del websites[:]

def daemon():
	while True:
		time.sleep(10)
		purge()
		get_sites()
		check_error_domains()
		for i in websites:
			errors(i)
		if errors_list:
			notify('\n'.join(errors_list), "Alert: Site Issues!")

def main():
	p = optparse.OptionParser()
	options, args = p.parse_args()

	if len(args) == 1:
		if args[0] == "start":
			start()
			daemon()
		if args[0] == "stop":
			stop()
	else:
		p.print_help()


if __name__ == '__main__':
	main()
